package com.laomuji.android.mvvm.view

import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import android.view.ViewConfiguration
import android.view.ViewParent
import android.widget.FrameLayout
import androidx.core.view.isNotEmpty
import androidx.viewpager2.widget.ViewPager2
import kotlin.math.abs
import kotlin.math.sign

class ViewPager2ScrollableContainer : FrameLayout {

    private var touchSlop: Int = 0
    private var initialX: Float = 0f
    private var initialY: Float = 0f

    private val parentViewPager: ViewPager2?
        get() {
            var v: ViewParent? = parent
            while (v != null && v !is ViewPager2) {
                v = v.parent
            }
            return v as? ViewPager2
        }

    private val childView: View?
        get() = if (isNotEmpty()) getChildAt(0) else null

    constructor(context: Context) : super(context) {
        init(context)
    }

    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
        init(context)
    }

    private fun init(context: Context) {
        touchSlop = ViewConfiguration.get(context).scaledTouchSlop
    }

    private fun canChildScroll(orientation: Int, delta: Float): Boolean {
        val direction = -sign(delta).toInt()
        val child = childView ?: return false

        return when (orientation) {
            ViewPager2.ORIENTATION_HORIZONTAL -> child.canScrollHorizontally(direction)
            ViewPager2.ORIENTATION_VERTICAL -> child.canScrollVertically(direction)
            else -> throw IllegalArgumentException()
        }
    }

    override fun onInterceptTouchEvent(e: MotionEvent): Boolean {
        handleInterceptTouchEvent(e)
        return super.onInterceptTouchEvent(e)
    }

    private fun handleInterceptTouchEvent(e: MotionEvent) {
        val currentParentViewPager = parentViewPager ?: return
        val orientation = currentParentViewPager.orientation
        if (!canChildScroll(orientation, -1f) && !canChildScroll(orientation, 1f)) {
            return
        }

        when (e.action) {
            MotionEvent.ACTION_DOWN -> {
                initialX = e.x
                initialY = e.y
                parent.requestDisallowInterceptTouchEvent(true)
            }

            MotionEvent.ACTION_MOVE -> {
                val dx = e.x - initialX
                val dy = e.y - initialY
                val isVpHorizontal = orientation == ViewPager2.ORIENTATION_HORIZONTAL
                val scaledDx = abs(dx) * if (isVpHorizontal) 0.5f else 1f
                val scaledDy = abs(dy) * if (isVpHorizontal) 1f else 0.5f
                if (scaledDx > touchSlop || scaledDy > touchSlop) {
                    if (isVpHorizontal == (scaledDy > scaledDx)) {
                        parent.requestDisallowInterceptTouchEvent(false)
                    } else {
                        if (canChildScroll(orientation, if (isVpHorizontal) dx else dy)) {
                            parent.requestDisallowInterceptTouchEvent(true)
                        } else {
                            parent.requestDisallowInterceptTouchEvent(false)
                        }
                    }
                }
            }
        }
    }
}